/*
 * @Author: zw 775925302@qq.com
 * @Date: 2023-02-06 22:06:56
 * @LastEditors: zhangwei
 * @LastEditTime: 2023-02-09 16:30:25
 * @FilePath: /z-lowcode-designerz/src/utils/func-program/MayBe.ts
 * @Description: 函子函数的应用，MayBe对传入的数据进行判空处理，并返回结果
 * 
 * 1. T: 泛型  -> 
 * 
 * 2. 构造函数 constructor
 * 
 * 
 * 需要实现的功能：
 * 
 * 1. 对传入的对象进行判空处理
 * 
 * 2. 判空后处理
 */


export class Maybe<T>{

    //value:T的T继承类MayBe<T>传递的值
    private constructor(private value:T | null){}

    getValue<T>(){
        return this.value;
    }

    isNull():Boolean{//判断值是否为空
        //对象
        if(this.value == null || this.value === undefined || this.value == ""){
            return true;
        }
        //数组

        if(this.value instanceof Array && this.value.length == 0){
            return true
        }

        return false
    }

    //拥有这个对象
    static own<T>(value:T){
        if(new Maybe(value).isNull()){
            return new Maybe<T>(null)
        }

        return new Maybe(value);
    }

    //要让Maybe类变得有用，我们要添加一些方法。你已经知道数组上可以调用map方法，对吧？就是把一个方法应用到数组的每个元素上。
    //如果我们把Maybe看做一个特殊的数组，即只有一个值或0个值的数组，那么我们也定义一个类似的map方法供我们使用。

    /**
     *  f: (wrapped: T) => R: 指定了参数f的类型是一个函数，函数有一个参数，类型是T
     *  R是类型参数，表示f转换函数的返回类型,可以叫G，H，K都行，只是一个描叙,没有实际含义
     * 
     *  Maybe<R>: 返回一个Maybe的对象，
     */
    map<R>(f: (wrapped: T) => R): Maybe<R> {
        if(this.value == null){//添加这行代码，主要是因为如果this.value为null的话，会和定义的参数T类型冲突，下面一行代码报错
            return new Maybe<R>(null)
        }
        var result = Maybe.own(f(this.value));
        if(result.value == null){
            console.error("函数执行错误",f)
        }
        return result;
    }

    //展开map，主要是针对多层嵌套时，返回对象是MayBe<R>时，如果在次基础上继续map会存在多层Maybe<Maybe<R>>情况
    flatMap<R>(f: (wrapped: T) => Maybe<R>) : Maybe<R> {
        if (this.value === null) {
            return new Maybe<R>(null);
        } else {
            return f(this.value);
        }
    }


    /**  举个列子
     * 
//对输入值判空，并且拥有值
const supervisorName = getSupervisorName(Maybe.own(employeeIdInputEl.value));

//注意flatMap,map的参数就是当前map所持有的值
function getSupervisorName(maybeEnteredId: Maybe<string>): Maybe<string> {
    return maybeEnteredId
        .flatMap(employeeIdString => Maybe.own(parseInt(employeeIdString))) // 转整得到employeeId
        .flatMap(employeeId => repository.findById(employeeId))  //通过employeeId查找到employee对象
        .flatMap(employee => employee.supervisorId)   //去对象的supervisorId得到supervisorId
        .flatMap(supervisorId => repository.findById(supervisorId)) //通过ID去找到supervisor对象
        .map(supervisor => supervisor.name);  //返回supervisor对象的名，最终是个字符串
}
     */
}